#include "pickup.h"

/**
 * 09/03/12 - Steven Hartin - Original Creation
 */

CPickup::CPickup(float fX, float fY, float fZ,
                 const string &szTextureName,
                 const string &szEntityName,
                 const ENTITY_ID &nId):
    //CMovableEntity(szEntityName, nId, fX, fY, fZ),
    CProjectile(szEntityName, "game/tile", nId, fX, fY, fZ),
    m_szTexture(szTextureName),
    bAppeared(false)
{
    /**
     * Constructor, ensure that we initialise the pickup, and set up the default
     * attributes of any pickup class. This class should never be instatiated
     * directly, instead, it should be subclassed by each individual pickup.
     *
     * @param const string &szTextureName The path to the texture to use.
     * @param const string &szMeshName The path to the mesh to use
     * @param const string &szEntityName The name of the entity
     * @param const ENTITY_ID &nId The ID of the pickup entity
     */
    setCollectible(true);

    CTexture *pTexture(
        CTextureContainer::getInstance()->getTexture(szTextureName));
    if (pTexture == nullptr)
    {
        pTexture = CTextureContainer::getInstance()->addTexture(szTextureName,
                                   szTextureName, 
                                   CDeviceManager::getInstance()->getDevice());
    }

    for (int i(0); i < 6; ++i)
    {
        getDisplayable()->setTexture(pTexture, i);
    }

    // 1 / sqrt(2) - at 45degrees this makes the diagonal the same size as 
    // 1 tile.
    getDisplayable()->setScale(0.707f, 0.707f, 0.707f);

    //CEntityContainer::getInstance()->addEntity(this);

    // Pickups should start invisible.
    setVisible(false);
}

CPickup::~CPickup()
{
    /**
     * Destructor, destory any buffs which have not yet been given to a player.
     */
    if (m_arrBuffs.size())
    {
        for (set<CBuff*>::iterator pBuff(m_arrBuffs.begin());
             pBuff != m_arrBuffs.end(); ++pBuff)
        {
            delete *pBuff;
        }
    }
}

void CPickup::addBuff(CBuff *pBuff)
{
    /**
     * Adds a buff to the pickup 'buff' set. This ensures that the buff is
     * added to the player when the pickup is picked up.
     *
     * @param CBuff *pBuff The pointer to the buff object.
     */
    m_arrBuffs.insert(pBuff);
}

bool CPickup::hasBuff(CBuff *pBuff)
{
    /**
     * @param CBuff *pBuff The pointer to the buff object.
     * @return bool Whether or not the buff exists on this pickup.
     */
    return m_arrBuffs.find(pBuff) != m_arrBuffs.end();
}

void CPickup::removeBuff(CBuff *pBuff)
{
    /**
     * Removes a buff from the buff list.
     *
     * @param CBuff *pBuff The pointer to the buff object.
     */
    set<CBuff*>::iterator pBuffPos(m_arrBuffs.find(pBuff));
    if (pBuffPos != m_arrBuffs.end())
    {
        m_arrBuffs.erase(pBuffPos);
    }
}

void CPickup::show()
{
    /**
     * Shows the pickup and applies an initial velocity to the object.
     */
    setVisible(true);
    setVelocity(0.0f, 5.0f, 0.0f);
    setInMotion(true);
    bAppeared = true;

    CSound *pSound2 = (CSoundManager::getInstance()->addSound(
            "pickup_spawn.wav"));
    pSound2->setVolume(0.4f);
    FMOD::Channel *pNewChannel(nullptr);
    pSound2->createNewChannel(&pNewChannel);
    pNewChannel->setPaused(false);
}

void CPickup::collect(CPlayer *pPlayer)
{
    /**
     * Executed when a player picks up this pickup. Ensure that all the buffs
     * are added to the player.
     *
     * @param CBuff *pBuff The pointer to the buff object.
     */
    if (pPlayer != nullptr)
    {
        if (m_arrBuffs.size())
        {
            for (set<CBuff*>::iterator pBuff(m_arrBuffs.begin());
                 pBuff != m_arrBuffs.end(); ++pBuff)
            {
                // Pass the buff onto the player
                pPlayer->applyBuff(*pBuff);
                //removeBuff((*pBuff));
            }
            m_arrBuffs.clear();
        }
    }

    setVisible(false);
    CMap *pMap(CMapContainer::getInstance()->getCurrentMap());
    if (pMap != nullptr)
    {
        int nHeight(0), nWidth(0), nDepth(0);
        pMap->getTilePositionFromCoord(nHeight, nWidth, nDepth, getX(), getY(),
            getZ(), 0);
        if (pMap->isValidTile(nHeight, nWidth, nDepth))
        {
            pMap->getTile(nHeight, nWidth, nDepth)->removeEntityFromBlock(this);
        }
    }
    CEntityContainer::getInstance()->removeEntity(this);
}

void CPickup::tick()
{
    /**
     * Executed every tick, ensure we rotate the block if it's appeared.
     */
    if (bAppeared)
    {
        getDisplayable()->setRotate(getDisplayable()->getRotateX(),
            getDisplayable()->getRotateY() + 0.5f,
            getDisplayable()->getRotateZ());
        CProjectile::tick();
    }
}